/*
 * Copyright 1999,2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.webduff.methods;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.googlecode.webduff.WebdavStatus;
import com.googlecode.webduff.exceptions.AccessDeniedException;
import com.googlecode.webduff.exceptions.MethodResponseError;
import com.googlecode.webduff.exceptions.ObjectAlreadyExistsException;
import com.googlecode.webduff.exceptions.ObjectNotFoundException;
import com.googlecode.webduff.exceptions.WebdavException;
import com.googlecode.webduff.io.URI;
import com.googlecode.webduff.locking.AcquiredLock;
import com.googlecode.webduff.locking.LockFailedException;
import com.googlecode.webduff.locking.ResourceLocks;

import java.util.Hashtable;
import java.io.IOException;

public class DoDelete extends ReportingMethod {

	private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(DoDelete.class);

    public MethodResponse execute(HttpServletRequest req, HttpServletResponse resp) throws IOException, MethodResponseError {
        URI theURI = getURIForRequest(req);
        MethodResponse theResponse = new MethodResponse(resp);
        AcquiredLock acquiredLock = null;
        
        try {
			acquiredLock = acquireExclusiveLock(theURI, ResourceLocks.INFINITE, req);
		} catch (LockFailedException e) {
			throw new MethodResponseError(WebdavStatus.SC_LOCKED);
		}
        
        try {
            Hashtable<String, Integer> errorList = new Hashtable<String, Integer>();
            deleteResource(theURI, errorList, theResponse, req);
            if (!errorList.isEmpty()) {
                sendReport(req, errorList, theResponse);
            }
        } catch (AccessDeniedException e) {
        	throw new MethodResponseError(WebdavStatus.SC_FORBIDDEN);
        } catch (ObjectAlreadyExistsException e) {
        	throw new MethodResponseError(WebdavStatus.SC_NOT_FOUND, req.getRequestURI());
        } catch (WebdavException e) {
        	throw new MethodResponseError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
        } catch(Throwable t) {
        	log.debug("DoDelete", t);
        } finally {
            acquiredLock.unlock();
        }
        
        return theResponse;
    }

    /**
     * deletes the recources at "path"
     *
     * @param uri
     *            the folder to be deleted
     * @param errorList
     *            all errors that ocurred
     * @param response TODO
     * @param req
     *            HttpServletRequest
     * @throws WebdavException
     *             if an error in the underlying store occurs
     * @throws IOException
     *             when an error occurs while sending the response
     * @throws MethodResponseError 
     */
    public void deleteResource(URI uri, Hashtable<String, Integer> errorList,
            MethodResponse response, HttpServletRequest req)
            throws IOException, WebdavException, MethodResponseError {
    	response.setStatusCode(WebdavStatus.SC_NO_CONTENT);
        if (store.isResource(uri)) {
            store.removeObject(uri);
        } else {
            if (store.isFolder(uri)) {
                deleteFolder(uri, errorList, req);
                store.removeObject(uri);
            } else {
            	throw new MethodResponseError(WebdavStatus.SC_NOT_FOUND);
            }
        }
    }


    /**
     *
     * helper method of deleteResource() deletes the folder and all of its
     * contents
     *
     * @param uri
     *            the folder to be deleted
     * @param errorList
     *            all errors that ocurred
     * @param req
     *            HttpServletRequest
     * @throws WebdavException
     *             if an error in the underlying store occurs
     */
    private void deleteFolder(URI uri, Hashtable<String, Integer> errorList, HttpServletRequest req) throws WebdavException {
        String[] children = store.getChildrenNames(uri);
        for (int i = children.length - 1; i >= 0; i--) {
            children[i] = "/" + children[i];
            try {
                if (store.isResource(uri.append(children[i]))) {
                    store.removeObject(uri.append(children[i]));
                } else {
                    deleteFolder(uri.append(children[i]), errorList, req);
                    store.removeObject(uri.append(children[i]));
                }
            } catch (AccessDeniedException e) {
                errorList.put(uri.append(children[i]).toString(), new Integer(WebdavStatus.SC_FORBIDDEN));
            } catch (ObjectNotFoundException e) {
                errorList.put(uri.append(children[i]).toString(), new Integer(WebdavStatus.SC_NOT_FOUND));
            } catch (WebdavException e) {
                errorList.put(uri.append(children[i]).toString(), new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
            }
        }
    }
}
